﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using JY.Common.EntityBase;

namespace JY.Common.Repository
{
    /// <summary>
    /// 只读工作单元
    /// </summary>
    public interface IUnitOfWorkOfQuery : IDisposable
    {
        //Single部分

        #region # 根据Id获取唯一实体对象（查看时用） —— T SingleOrDefault(Guid id)

        /// <summary>
        /// 根据Id获取唯一实体对象（查看时用），
        /// </summary>
        /// <param name="id">标识Id</param>
        /// <returns>实体对象</returns>
        /// <remarks>无该对象时返回null</remarks>
        T SingleOrDefault<T>(Guid id) where T : PlainEntity;
        #endregion

        #region # 根据Id获取唯一实体对象（查看时用） —— T Single(Guid id)

        /// <summary>
        /// 根据Id获取唯一实体对象（查看时用），
        /// </summary>
        /// <param name="id">标识Id</param>
        /// <returns>实体对象</returns>
        T Single<T>(Guid id) where T : PlainEntity;
        #endregion

        #region # 根据编号获取唯一实体对象（查看时用） —— T SingleOrDefault(string number)

        /// <summary>
        /// 根据编号获取唯一实体对象（查看时用），
        /// </summary>
        /// <param name="number">编号</param>
        /// <returns>实体对象</returns>
        /// <remarks>无该对象时返回null</remarks>
        T SingleOrDefault<T>(string number) where T : RootEntity;
        #endregion

        #region # 根据编号获取唯一实体对象（查看时用） —— T Single(string number)

        /// <summary>
        /// 根据编号获取唯一实体对象（查看时用），
        /// </summary>
        /// <param name="number">编号</param>
        /// <returns>实体对象</returns>
        T Single<T>(string number) where T : RootEntity;
        #endregion

        #region # 获取默认或第一个实体对象 —— T FirstOrDefault()

        /// <summary>
        /// 获取默认或第一个实体对象，
        /// </summary>
        /// <remarks>无该对象时返回null</remarks>
        T FirstOrDefault<T>() where T : PlainEntity;
        #endregion

        #region # 根据条件获取唯一实体对象（查看时用） —— T SingleOrDefault(Expression<Func<T, bool>> predicate)

        /// <summary>
        /// 根据条件获取唯一实体对象（查看时用），
        /// </summary>
        /// <param name="predicate">条件</param>
        /// <returns>实体对象</returns>
        /// <remarks>无该对象时返回null</remarks>
        T SingleOrDefault<T>(Expression<Func<T, bool>> predicate) where T : PlainEntity;
        #endregion

        #region # 根据条件获取第一个实体对象（查看时用） —— T FirstOrDefault(Expression<Func<T, bool>> predicate)

        /// <summary>
        /// 根据条件获取第一个实体对象（查看时用），
        /// </summary>
        /// <param name="predicate">条件</param>
        /// <returns>实体对象</returns>
        /// <remarks>无该对象时返回null</remarks>
        T FirstOrDefault<T>(Expression<Func<T, bool>> predicate) where T : PlainEntity;
        #endregion

        //ICollection部分

        #region # 获取实体对象列表 —— ICollection<T> FindAll()

        /// <summary>
        /// 获取实体对象列表
        /// </summary>
        /// <returns>实体对象列表</returns>
        ICollection<T> FindAll<T>() where T : PlainEntity;
        #endregion

        #region # 根据关键字获取实体对象列表 —— ICollection<T> Find(string keywords)

        /// <summary>
        /// 根据关键字获取实体对象列表
        /// </summary>
        /// <returns>实体对象列表</returns>
        ICollection<T> Find<T>(string keywords) where T : RootEntity;
        #endregion

        #region # 根据条件获取实体对象列表 —— IQueryable<T> Find(Expression<Func<T, bool>> predicate)

        /// <summary>
        /// 根据条件获取实体对象列表
        /// </summary>
        /// <param name="predicate">条件表达式</param>
        /// <returns>实体对象列表</returns>
        IQueryable<T> Find<T>(Expression<Func<T, bool>> predicate) where T : PlainEntity;
        #endregion

        #region # 根据条件获取实体对象列表（默认排序） —— virtual IOrderedQueryable<T> FindBySort(...

        /// <summary>
        /// 根据条件获取实体对象列表（默认排序）
        /// </summary>
        /// <returns>实体对象列表</returns>
        IOrderedQueryable<T> FindBySort<T>(Expression<Func<T, bool>> condition) where T : PlainEntity;
        #endregion

        #region # 根据条件获取实体对象Id列表 —— IQueryable<Guid> FindIds(Expression<Func<T, bool>> predicate)

        /// <summary>
        /// 根据条件获取实体对象Id列表
        /// </summary>
        /// <param name="predicate">条件表达式</param>
        /// <returns>实体对象Id列表</returns>
        IQueryable<Guid> FindIds<T>(Expression<Func<T, bool>> predicate) where T : PlainEntity;
        #endregion

        #region # 根据条件分页获取实体对象列表 —— IQueryable<T> FindByPage(...

        /// <summary>
        /// 根据条件分页获取实体对象列表
        /// </summary>
        /// <param name="predicate">条件表达式</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <param name="rowCount">总记录条数</param>
        /// <param name="pageCount">总页数</param>
        /// <returns>实体对象列表</returns>
        IQueryable<T> FindByPage<T>(Expression<Func<T, bool>> predicate, int pageIndex, int pageSize, out int rowCount, out int pageCount) where T : PlainEntity;
        #endregion

        #region # 根据关键字分页获取实体对象列表 —— ICollection<T> FindByPage(...

        /// <summary>
        /// 根据关键字分页获取实体对象列表
        /// </summary>
        /// <param name="keywords">关键字</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="pageSize">页容量</param>
        /// <param name="rowCount">总记录条数</param>
        /// <param name="pageCount">总页数</param>
        /// <returns>实体对象列表</returns>
        ICollection<T> FindByPage<T>(string keywords, int pageIndex, int pageSize, out int rowCount, out int pageCount) where T : RootEntity;
        #endregion


        //IDictionary部分

        #region # 根据Id集获取实体对象字典 —— IDictionary<Guid, T> Find(IEnumerable<Guid> ids)

        /// <summary>
        /// 根据Id集获取实体对象字典
        /// </summary>
        /// <returns>实体对象字典</returns>
        /// <remarks>IDictionary[Guid, T]，[Id, 实体对象]</remarks>
        IDictionary<Guid, T> Find<T>(IEnumerable<Guid> ids) where T : PlainEntity;
        #endregion

        #region # 根据编号集获取实体对象字典 —— IDictionary<string, T> Find(IEnumerable<string> numbers)

        /// <summary>
        /// 根据编号集获取实体对象字典
        /// </summary>
        /// <returns>实体对象字典</returns>
        /// <remarks>IDictionary[string, T]，[编号, 实体对象]</remarks>
        IDictionary<string, T> Find<T>(IEnumerable<string> numbers) where T : RootEntity;
        #endregion

        //Count部分

        #region # 获取总记录条数 —— int Count()

        /// <summary>
        /// 获取总记录条数
        /// </summary>
        /// <returns>总记录条数</returns>
        int Count<T>() where T : PlainEntity;
        #endregion

        #region # 根据条件获取记录条数 —— int Count(Expression<Func<T, bool>> predicate)

        /// <summary>
        /// 根据条件获取记录条数
        /// </summary>
        /// <param name="predicate">条件表达式</param>
        /// <returns>符合条件的记录条数</returns>
        int Count<T>(Expression<Func<T, bool>> predicate) where T : PlainEntity;
        #endregion

        //Exists部分

        #region # 是否存在给定条件的实体对象 —— bool Exists(Expression<Func<T, bool>> predicate)

        /// <summary>
        /// 是否存在给定条件的实体对象
        /// </summary>
        /// <param name="predicate">条件</param>
        /// <returns>是否存在</returns>
        bool Exists<T>(Expression<Func<T, bool>> predicate) where T : PlainEntity;
        #endregion

        #region # 是否存在给定Id的实体对象 —— bool Exists(Guid id)

        /// <summary>
        /// 是否存在给定Id的实体对象
        /// </summary>
        /// <param name="id">标识Id</param>
        /// <returns>是否存在</returns>
        bool Exists<T>(Guid id) where T : PlainEntity;
        #endregion

        #region # 是否存在给定编号的实体对象 —— bool ExistsNo(string number)

        /// <summary>
        /// 是否存在给定编号的实体对象
        /// </summary>
        /// <param name="number">编号</param>
        /// <returns>是否存在</returns>
        bool ExistsNo<T>(string number) where T : RootEntity;
        #endregion

        #region # 是否存在给定编号的实体对象 —— bool ExistsNo(Guid? id, string number)

        /// <summary>
        /// 是否存在给定编号的实体对象
        /// </summary>
        /// <param name="id">标识id</param>
        /// <param name="number">编号</param>
        /// <returns>是否存在</returns>
        bool ExistsNo<T>(Guid? id, string number) where T : RootEntity;
        #endregion

        #region # 是否存在给定名称的实体对象 —— bool ExistsName(string name)

        /// <summary>
        /// 是否存在给定名称的实体对象
        /// </summary>
        /// <param name="name">名称</param>
        /// <returns>是否存在</returns>
        bool ExistsName<T>(string name) where T : RootEntity;
        #endregion

        #region # 是否存在给定名称的实体对象 —— bool ExistsName(Guid? id, string name)

        /// <summary>
        /// 是否存在给定名称的实体对象
        /// </summary>
        /// <param name="id">标识id</param>
        /// <param name="name">名称</param>
        /// <returns>是否存在</returns>
        bool ExistsName<T>(Guid? id, string name) where T : RootEntity;
        #endregion

        #region # 是否存在给定名称的实体对象 —— bool ExistsName(string number, string name)

        /// <summary>
        /// 是否存在给定名称的实体对象
        /// </summary>
        /// <param name="number">编号</param>
        /// <param name="name">名称</param>
        /// <returns>是否存在</returns>
        bool ExistsName<T>(string number, string name) where T : RootEntity;
        #endregion

        //其他

        #region # 执行SQL查询 —— ICollection<TEntity> ExecuteSqlQuery<TEntity>(string sql...

        /// <summary>
        /// 执行SQL查询
        /// </summary>
        /// <param name="sql">SQL语句</param>
        /// <param name="parameters">参数集</param>
        /// <returns>实体对象列表</returns>
        ICollection<T> ExecuteSqlQuery<T>(string sql, params object[] parameters);

        #endregion
    }
}
